﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Markup;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Expression.Samples.Interactivity.DataHelpers;
using Interactivity = System.Windows.Interactivity;

namespace XamlingCore.SL.Controls.Behavior
{
    /// <summary>
    /// Switches between multiple visual states depending on a condition.
    /// Based on DataStateSwitchBehavior from expressionblend.codeplex.com
    /// </summary>
    [ContentProperty("States")]
    public class ObjectTypeSwitchBehavior : Interactivity.Behavior<FrameworkElement>
    {

        /// <summary>
        /// Backing DependencyProperty for Binding.
        /// </summary>
        public static readonly DependencyProperty BindingProperty = DependencyProperty.Register("Binding", typeof(Object), typeof(ObjectTypeSwitchBehavior), new PropertyMetadata(null, ObjectTypeSwitchBehavior.HandleBindingChanged));
        /// <summary>
        /// Backing DependencyProperty for States.
        /// </summary>
        public static readonly DependencyProperty StatesProperty = DependencyProperty.Register("States", typeof(List<ObjectTypeSwitchCase>), typeof(ObjectTypeSwitchBehavior), new PropertyMetadata(null));

       

        /// <summary>
        /// Constructor
        /// </summary>
        public ObjectTypeSwitchBehavior()
        {
            this.States = new List<ObjectTypeSwitchCase>();
        }

        /// <summary>
        /// Binding to be evaluated.
        /// </summary>
        public Object Binding
        {
            get { return (Object)this.GetValue(ObjectTypeSwitchBehavior.BindingProperty); }
            set { this.SetValue(ObjectTypeSwitchBehavior.BindingProperty, value); }
        }

        /// <summary>
        /// Various states on which this is active or not.
        /// </summary>
        public List<ObjectTypeSwitchCase> States
        {
            get { return (List<ObjectTypeSwitchCase>)this.GetValue(ObjectTypeSwitchBehavior.StatesProperty); }
            set { this.SetValue(ObjectTypeSwitchBehavior.StatesProperty, value); }
        }

        private static void HandleBindingChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
        {
            ((ObjectTypeSwitchBehavior)sender).OnBindingChanged(e);
        }

        /// <summary>
        /// Notification that the Binding property has changed.
        /// </summary>
        /// <param name="e"></param>
        protected virtual void OnBindingChanged(DependencyPropertyChangedEventArgs e)
        {
            Dispatcher.BeginInvoke(() => { CheckState(); });
            
            //this.listener.Binding = (Binding)e.NewValue;
        }

        /// <summary>
        /// Performs some initialization.
        /// </summary>
        protected override void OnAttached()
        {
            base.OnAttached();

            //this.listener.Element = this.AssociatedObject;
        }

        /// <summary>
        /// Performs some cleanup.
        /// </summary>
        protected override void OnDetaching()
        {
            base.OnDetaching();

            //this.listener.Element = null;
        }

        private void HandleBindingValueChanged(object sender, BindingChangedEventArgs e)
        {
            this.CheckState();
        }

        private void CheckState()
        {
            foreach (ObjectTypeSwitchCase switchCase in this.States)
            {
                if (switchCase.IsValid(this.Binding))
                {
                    FrameworkElement targetElement = GoToStateBase.FindTargetElement(this.AssociatedObject);
                    if (targetElement != null)
                    {
                        GoToStateBase.GoToState(targetElement, switchCase.State, true);
                    }
                    break;
                }
            }
        }
    }

    /// <summary>
    /// Represents a case to check if the visual state should be activated.
    /// </summary>
    public class ObjectTypeSwitchCase
    {

        /// <summary>
        /// The value to be compared against
        /// </summary>
        public string TypeName { get; set; }

        /// <summary>
        /// The name of the state to be activated if the value is true
        /// </summary>
        public string State { get; set; }

        /// <summary>
        /// Compares this value to the target value to determine if the
        /// state should be activated.
        /// </summary>
        /// <param name="targetValue"></param>
        /// <returns></returns>
        public bool IsValid(object targetValue)
        {
            if(TypeName == "*" || string.IsNullOrEmpty(TypeName))
            {
                return true;
            }

            var type = targetValue.GetType().FullName;
            
            return type.IndexOf(TypeName) != -1;
        }
    }
}
